import PlatformsList from '../../components/PlatformsList/PlatformsList.tsx';

# DRM

## DRM Example

We provide a sample implementation in the [example app](https://github.com/TheWidlarzGroup/react-native-video/blob/master/examples/common/DRMExample.tsx) demonstrating how to use DRM with `react-native-video`. You’ll need a valid token—visit [our site](https://www.thewidlarzgroup.com/services/free-drm-token-generator-for-video?utm_source=rnv&utm_medium=docs&utm_campaign=drm&utm_id=text) to obtain a **free 24-hour token**.

## DRM Offline

If you need DRM-protected content available offline, our [Offline Video SDK](https://sdk.thewidlarzgroup.com/offline-video/?utm_source=rnv&utm_medium=docs&utm_campaign=drm&utm_id=offline-video-sdk-link) enables downloading, storing, and managing streams with and without DRM. It also handles many edge cases you may encounter over time.

### Prerequisites:
- Use `react-native-video` v6 or v7. If you're still on v5 or lower, [contact us](https://www.thewidlarzgroup.com/?utm_source=rnv&utm_medium=docs&utm_campaign=drm&utm_id=upgrade-contact#Contact) for assistance.

> Supporting our software kits helps maintain this open-source project. Thank you!

## Providing DRM Data (Tested with HTTP/HTTPS Assets)

You can configure DRM playback by providing a DRM object with the following properties. This feature disables the use of `TextureView` on Android.

### DRM Properties

### `base64Certificate`

<PlatformsList types={['iOS', 'visionOS']} />

**Type:** boolean
**Default:** `false`

Indicates whether the certificate URL returns data in Base64 format.

### `certificateUrl`

<PlatformsList types={['iOS', 'visionOS']} />

**Type:** string
**Default:** `undefined`

The URL used to fetch a valid certificate for FairPlay.

### `getLicense`

<PlatformsList types={['iOS', 'visionOS']} />

**Type:** function
**Default:** `undefined`

Instead of setting `licenseServer`, you can manually acquire the license in JavaScript and send the result to the native module for FairPlay DRM configuration.

The following parameters are available in `getLicense`:
- `contentId`: The content ID from the DRM object or `loadingRequest.request.url?.host`
- `loadedLicenseUrl`: The URL retrieved from `loadingRequest.request.URL.absoluteString`, starting with `skd://` or `clearkey://`
- `licenseServer`: The URL passed in the DRM object
- `spcString`: The SPC used for DRM validation

You should return a Base64-encoded CKC response, either directly or as a `Promise`.

#### Example:

```js
getLicense: (spcString, contentId, licenseUrl, loadedLicenseUrl) => {
  const base64spc = Base64.encode(spcString);
  const formData = new FormData();
  formData.append('spc', base64spc);
  return fetch(`https://license.pallycon.com/ri/licenseManager.do`, {
    method: 'POST',
    headers: {
      'pallycon-customdata-v2': 'your-custom-header',
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: formData,
  })
    .then((response) => response.text())
    .then((response) => response)
    .catch((error) => console.error('Error', error));
};
```

### `contentId`

<PlatformsList types={['iOS', 'visionOS']} />

**Type:** string
**Default:** `undefined`

Sets the content ID for the stream. If not specified, the system uses the host value from `loadingRequest.request.URL.host`.

### `headers`

<PlatformsList types={['Android', 'iOS', 'visionOS']} />

**Type:** Object
**Default:** `undefined`

Custom headers for the license server request.

#### Example:

```js
drm: {
  type: DRMType.WIDEVINE,
  licenseServer: 'https://drm-widevine-licensing.axtest.net/AcquireLicense',
  headers: {
    'X-AxDRM-Message': 'your-drm-header',
  },
}
```

### `licenseServer`

<PlatformsList types={['Android', 'iOS', 'visionOS']} />

**Type:** string
**Default:** `undefined`

The license server URL that authorizes protected content playback.

### `multiDrm`

<PlatformsList types={['Android']} />

**Type:** boolean
**Default:** `false`

Indicates whether the DRM system should support key rotation. See [Android Developer Docs](https://developer.android.google.cn/media/media3/exoplayer/drm?hl=en#key-rotation) for more details.

### `type`

<PlatformsList types={['Android', 'iOS']} />

**Type:** DRMType
**Default:** `undefined`

Defines the DRM type:
- **Android:** `DRMType.WIDEVINE`, `DRMType.PLAYREADY`, `DRMType.CLEARKEY`
- **iOS:** `DRMType.FAIRPLAY`

### `localSourceEncryptionKeyScheme`

<PlatformsList types={['iOS', 'visionOS']} />

**Type:** string

Sets the URL scheme for stream encryption keys used in local assets.

#### Example:

```js
localSourceEncryptionKeyScheme="my-offline-key"
```

## Common Usage Scenarios

### Sending Cookies to the License Server

You can send cookies using the `headers` prop.

#### Example:

```js
drm: {
  type: DRMType.WIDEVINE,
  licenseServer: 'https://drm-widevine-licensing.axtest.net/AcquireLicense',
  headers: {
    'Cookie': 'PHPSESSID=your-session-id; csrftoken=mytoken; _gat=1; foo=bar'
  },
}
```

### Custom License Acquisition (iOS Only)

#### Example:

```js
drm: {
  type: DRMType.FAIRPLAY,
  getLicense: (spcString) => {
    const base64spc = Base64.encode(spcString);
    return fetch('YOUR_LICENSE_SERVER_URL', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json',
      },
      body: JSON.stringify({
        getFairplayLicense: {
          foo: 'bar',
          spcMessage: base64spc,
        }
      })
    })
      .then(response => response.json())
      .then((response) => {
        if (response?.getFairplayLicenseResponse?.ckcResponse) {
          return response.getFairplayLicenseResponse.ckcResponse;
        }
        throw new Error('No valid response');
      })
      .catch((error) => console.error('CKC error', error));
  }
}
```
